/*
 * Copyright (C) 2011, EADS France
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */
package xowl.gmi.environment;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import xowl.utils.config.Configuration;

/**
 *
 * @author Laurent WOUTERS
 */
public class ProjectController implements xowl.gmi.view.ProjectNode.Actions {
    private MainController parent;
    private String projectFile;
    private xowl.gmi.model.Project model;
    private xowl.gmi.view.ProjectNode view;
    private List<DiagramController> diagrams;
    private xowl.lang.owl2.Ontology ontology;
    private boolean isModified;
    
    public xowl.utils.logging.Logger getLog() { return parent.getLog(); }
    public Options getOptions() { return parent.getOptions(); }
    public Locale getLocale() { return parent.getLocale(); }
    public xowl.interpreter.Repository getRepository() { return parent.getRepository(); }
    public xowl.gmi.model.Project getModel() { return model; }
    public xowl.gmi.view.ProjectNode getView() { return view; }
    public List<DiagramController> getDiagrams() { return diagrams; }
    public xowl.lang.owl2.Ontology getOntology() { return ontology; }
    public boolean isModified() { return isModified; }
    
    public ProjectController(MainController parent, String name) {
        this.parent = parent;
        this.projectFile = "workspace/" + name + ".project";
        String file = "workspace/" + name + ".owl";
        String uri = "http://www.xowl.org/gmi/workspace/" + name + "/model";
        
        this.model = new xowl.gmi.model.Project(name, file);
        this.view = new xowl.gmi.view.ProjectNode(this, parent.getLocale(), name);
        for (xowl.gmi.model.ExecutionEntry entry : parent.getWorkbench().getExecEntries())
            this.view.addExecutionChoice(entry.getID(), entry.getName());
        this.diagrams = new ArrayList<>();
        this.ontology = parent.getRepository().resolveOntology(uri);
        this.isModified = false;
    }
    public ProjectController(MainController parent, xowl.gmi.model.Project model, String file) {
        this.parent = parent;
        this.projectFile = file;
        this.model = model;
        this.view = new xowl.gmi.view.ProjectNode(this, parent.getLocale(), model.getName());
        for (xowl.gmi.model.ExecutionEntry entry : parent.getWorkbench().getExecEntries())
            this.view.addExecutionChoice(entry.getID(), entry.getName());
        this.diagrams = new ArrayList<>();
        for (xowl.gmi.model.Diagram dm : model.getDiagrams()) {
            DiagramController dc = new DiagramController(this, dm);
            diagrams.add(dc);
            view.addDiagram(dc.getViewNode());
        }
        this.ontology = parent.getRepository().loadOntology(model.getFile(), xowl.interpreter.OWL2Syntax.Functional);
        this.isModified = false;
    }
    
    @Override public void onDiagramAdd() {
        xowl.gmi.view.DialogNewDiagram dialog = new xowl.gmi.view.DialogNewDiagram(parent.getLocale(), parent.getView().getFrame(), false);
        dialog.addProject(this, model.getName());
        for (xowl.gmi.model.WorkbenchView wbv : parent.getWorkbench().getViews())
            dialog.addWBView(wbv, wbv.getName());
        dialog.prepare();
        dialog.setVisible(true);
        if (!dialog.isAccept())
            return;
        addDiagram(dialog.getSelectedName(), (xowl.gmi.model.WorkbenchView)dialog.getSelectedView());
    }
    
    @Override public void onSave() {
        parent.getRepository().writeOntology(ontology, model.getFile(), xowl.interpreter.OWL2Syntax.Functional);
        for (DiagramController diagram : diagrams)
            diagram.onSave();
        Configuration config = new Configuration();
        model.save(config);
        try { config.save(projectFile, Charset.forName("UTF-8")); }
        catch (IOException ex) { parent.getLog().error(MainController.name, "Failed to save project to " + projectFile, ex); }
        isModified = false;
        view.setModified(isModified);
    }
    
    @Override public void onSaveAs() {
        view.setModified(false);
    }
    
    @Override public void onClose() {
        if (isModified) {
            int res = showConfirm(parent.getLocale().projectClose.replace("{1}", model.getName()), true);
            if (res == javax.swing.JOptionPane.CANCEL_OPTION)
                return;
            if (res == javax.swing.JOptionPane.YES_OPTION)
                onSave();
        }
        for (DiagramController diagram : diagrams)
            diagram.onClose();
        parent.removeProject(this);
        parent.getRepository().dropOntology(ontology);
    }
    
    @Override public void onExecute(String id) { execute(parent.getWorkbench().getExecEntry(id), new xowl.lang.runtime.Value[]{}); }
    
    public void executeOnObject(xowl.lang.owl2.IRI object, xowl.gmi.model.ExecutionEntry entry) {
        xowl.lang.runtime.Value[] params = new xowl.lang.runtime.Value[]{parent.getRepository().resolveEntity(object)};
        execute(entry, params);
    }
    private void execute(xowl.gmi.model.ExecutionEntry entry, xowl.lang.runtime.Value[] params) {
        ProjectExecution exec = new ProjectExecution(parent, entry, params);
        exec.run();
    }
    
    public void onDiagramModify() {
        isModified = true;
        view.setModified(isModified);
    }
    
    public void executeUIAction(UIAction action) { parent.executeUIAction(action); }
    
    public DiagramController addDiagram(String name, xowl.gmi.model.WorkbenchView wbv) { return addDiagram(name, wbv, null); }
    public DiagramController addDiagram(String name, xowl.gmi.model.WorkbenchView wbv, String root) {
        xowl.gmi.model.Diagram dm = new xowl.gmi.model.Diagram(name, wbv, root);
        DiagramController diagram = new DiagramController(this, dm);
        model.addDiagram(diagram.getModel());
        view.addDiagram(diagram.getViewNode());
        diagrams.add(diagram);
        diagram.onOpen();
        isModified = true;
        view.setModified(isModified);
        return diagram;
    }
    
    public void removeDiagram(DiagramController diagram) {
        model.removeDiagram(diagram.getModel());
        view.removeDiagram(diagram.getViewNode());
        diagrams.remove(diagram);
        isModified = true;
        view.setModified(isModified);
    }
    
    public void openDiagram(DiagramController diagram) { parent.openDiagram(diagram); }
    public void closeDiagram(DiagramController diagram) { parent.closeDiagram(diagram); }
    
    public int showConfirm(String message, boolean canCancel) { return parent.showConfirm(message, canCancel); }
    
    @Override public String toString() { return model.getName(); }
}
